﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using Microsoft.Xna.Framework.Content;

namespace Common.Resources
{
    public class ResourcesManager<TKey, TValue> : Dictionary<TKey, TValue>, IDisposable where TValue : class
    {
        private ContentManager _content;
        private bool isLoading = false;
        private bool isExiting = false;
        private Thread tr;
        public ResourcesManager(ContentManager content)
        {
            _content = content;
            tr = new Thread(() =>
            {
                Thread.Sleep(200000);
                while (!isExiting)
                {
                    if (isLoading)
                    {
                        Thread.Sleep(100);//происходит загрузка ресурса, нельзя очищать буфер, ждем...
                    }
                    else
                    {
                        Thread.Sleep(100);//на всякий случай ждать пока передадутся все объекты
                        ClearArray();
                        Thread.Sleep(200000);//выгружать ресурсы каждые 200 секунд
                    }
                }
            });

        }
        void ClearArray()
        {
            _content.Unload();
            this.Clear();
        }
        public void Exit()
        {
            isExiting = true;
        }
        public TValue GetResource(TKey key, Type t)
        {
            isLoading = true;
            if (this.ContainsKey(key))
            {
                isLoading = false;
                return this[key];
            }
            else
            {
                //loadList[obj.Key] = _content.Load<t>(obj.Key);
                MethodInfo method = this.GetType().GetMethod("Load", BindingFlags.NonPublic | BindingFlags.Instance);
                MethodInfo closedMethod = method.MakeGenericMethod(t);

                this.Add(key, closedMethod.Invoke(this, new object[] { key }) as TValue);
                isLoading = false;
                return this[key];
            }
        }
        public TValue[] GetResources(TKey[] key, Type t)
        {
            isLoading = true;
            List<TValue> result = new List<TValue>();
            foreach (TKey k in key)
            {
                if (this.ContainsKey(k))
                {
                    result.Add(this[k]);
                }
                else
                {
                    //loadList[obj.Key] = _content.Load<t>(obj.Key);
                    MethodInfo method = this.GetType().GetMethod("Load", BindingFlags.NonPublic | BindingFlags.Instance);
                    MethodInfo closedMethod = method.MakeGenericMethod(t);

                    this.Add(k, closedMethod.Invoke(this, new object[] { k }) as TValue);
                    result.Add(this[k]);
                }
            }
            isLoading = false;
            return result.ToArray();
        }

        private T Load<T>(string path)
        {
            return _content.Load<T>(path);
        }

        public void Dispose()
        {
            try
            {
                tr.Abort();
            }
            catch (Exception)
            {}
            try
            {
                ClearArray();
            }
            catch (Exception)
            {
                Thread.Sleep(100);
                ClearArray();
            }
            _content = null;
        }
    }
}
